﻿#region Class Header
/* ========================================================================
* 【本类功能概述】
* 
* 作者：chinesedragon 
* 时间：4/26/2013 1:14:22 PM
* 文件名：TooltipListBox
* 版本：V1.0.1
*
* 修改时间： 
* 修改说明：
* ========================================================================
*/
#endregion

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace TooltipListBox
{
    #region interface ITooltipDisplayer

    /// <summary>
    /// 
    /// </summary>
    internal interface ITooltipDisplayer
    {
        string GetTooltipText();
    }

    #endregion

    #region class ListBoxItem

    /// <summary>
    /// 
    /// </summary>
    internal class ListBoxItem : ITooltipDisplayer
    {
        /// <summary>
        /// 要显示的文字
        /// </summary>
        public string DisplayText { get; private set; }
        /// <summary>
        /// 提示文字
        /// </summary>
        public string TooltipText { get; private set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="textForDisplay">要显示的文字</param>
        /// <param name="textForTooltip">提示文字</param>
        public ListBoxItem(string textForDisplay, string textForTooltip)
        {
            DisplayText = textForDisplay;
            TooltipText = textForTooltip;
        }

        /// <summary>
        /// 将对象以字符串显示
        /// </summary>
        /// <returns>要显示的文字</returns>
        public override string ToString()
        {
            return DisplayText;
        }

        /// <summary>
        /// 返回提示文字
        /// </summary>
        /// <returns>提示文字</returns>
        public string GetTooltipText()
        {
            return TooltipText;
        }
    }

    #endregion

    /// <summary>
    /// 
    /// </summary>
    public partial class TooltipListBox : ListBox
    {
        private int currentItem;
        private bool currentItemSet;
        private bool tooltipDisplayed;
        private Timer tooltipDisplayTimer;
        private ToolTip tooltip;

        public TooltipListBox()
        {
            InitializeComponent();

            this.MouseMove += TooltipListBox_MouseMove;
            this.MouseLeave += TooltipListBox_MouseLeave;

            currentItemSet = false;
            tooltipDisplayed = false;
            tooltipDisplayTimer = new Timer();
            tooltip = new ToolTip();

            tooltipDisplayTimer.Interval = SystemInformation.MouseHoverTime;
            tooltipDisplayTimer.Tick += tooltipDisplayTimer_Tick;
        }

        public bool IsBalloon
        {
            get
            {
                if (tooltip != null)
                    return tooltip.IsBalloon;
                else
                {
                    tooltip = new ToolTip();
                    return tooltip.IsBalloon;
                }
            }
            set
            {
                if (tooltip == null)
                    tooltip = new ToolTip();
                tooltip.IsBalloon = value;
            }
        }

        private void TooltipListBox_MouseMove(object sender, MouseEventArgs e)
        {
            Point cursorPoint = Cursor.Position;
            cursorPoint = this.PointToClient(cursorPoint);
            int itemIndex = this.IndexFromPoint(cursorPoint);

            if (itemIndex == ListBox.NoMatches)
            {//Mouse over empty space in the Listbox so hide tooltip
                tooltip.Hide(this);
                currentItemSet = false;
                tooltipDisplayed = false;
                tooltipDisplayTimer.Stop();
            }
            else if (!currentItemSet)
            {//Mouse over a new item so start timer to display tooltip
                currentItem = itemIndex;
                currentItemSet = true;
                tooltipDisplayTimer.Start();
            }
            else if (itemIndex != currentItem)
            {//mouse over a different item so hide tooltip and restart timer
                currentItem = itemIndex;
                tooltip.Hide(this);
                tooltipDisplayed = false;
                tooltipDisplayTimer.Stop();
                tooltipDisplayTimer.Start();
            }
        }

        private void TooltipListBox_MouseLeave(object sender, EventArgs e)
        {//Mouse has left listbox so stop timer (tooltip is automatically hidden)
            currentItemSet = false;
            tooltipDisplayed = false;
            tooltipDisplayTimer.Stop();
        }

        private void tooltipDisplayTimer_Tick(object sender, EventArgs e)
        {//Display tooltip text since mouse has havored over an item
            if ( !tooltipDisplayed
                && currentItem != ListBox.NoMatches
                && currentItem<this.Items.Count)
            {
                ITooltipDisplayer player = this.Items[currentItem] as ITooltipDisplayer;
                if (player != null)
                {
                    tooltip.SetToolTip(this, player.GetTooltipText());
                    tooltipDisplayed = true;
                }
            }
        }
    }
}
